﻿//EmulationControlPanel.xaml.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Xaml
{
	using System;
	using System.Windows;

	using Ecng.Common;
	using Ecng.Xaml;

	using StockSharp.Algo.Testing;

	/// <summary>
	/// Графическая панель для управления процессом эмуляции.
	/// </summary>
	public partial class EmulationControlPanel
	{
		private TimeSpan _progressStep;
		private DateTime _nextTime;
		private DateTime _stopTime;

		/// <summary>
		/// Создать <see cref="EmulationControlPanel"/>.
		/// </summary>
		public EmulationControlPanel()
		{
			InitializeComponent();
		}

		private IEmulationTrader _emulationTrader;

		/// <summary>
		/// Эмуляционный шлюз.
		/// </summary>
		public IEmulationTrader EmulationTrader
		{
			get { return _emulationTrader; }
			set
			{
				if (value == EmulationTrader)
					return;

				if (_emulationTrader != null)
				{
					_emulationTrader.StateChanged -= EmulationTraderOnStateChanged;
					_emulationTrader.MarketTimeChanged -= EmulationTraderOnMarketTimeChanged;
					Start.IsEnabled = false;
				}

				_emulationTrader = value;

				if (_emulationTrader != null)
				{
					_emulationTrader.StateChanged += EmulationTraderOnStateChanged;
					_emulationTrader.MarketTimeChanged += EmulationTraderOnMarketTimeChanged;
					Start.IsEnabled = true;
				}
			}
		}

		private void EmulationTraderOnMarketTimeChanged(TimeSpan timeSpan)
		{
			if (EmulationTrader.CurrentTime >= _nextTime || EmulationTrader.CurrentTime >= _stopTime)
			{
				_nextTime += _progressStep;
				GuiDispatcher.GlobalDispatcher.AddAction(() => Progress.Value++);
			}
		}

		/// <summary>
		/// <see cref="DependencyProperty"/> для <see cref="From"/>.
		/// </summary>
		public static readonly DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(DateTime), typeof(EmulationControlPanel), new PropertyMetadata(DateTime.MinValue));

		/// <summary>
		/// Дата начала тестирования.
		/// </summary>
		public DateTime From
		{
			get { return (DateTime)GetValue(FromProperty); }
			set { SetValue(FromProperty, value); }
		}

		/// <summary>
		/// <see cref="DependencyProperty"/> для <see cref="To"/>.
		/// </summary>
		public static readonly DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(DateTime), typeof(EmulationControlPanel), new PropertyMetadata(DateTime.MinValue));

		/// <summary>
		/// Дата окончания тестирования.
		/// </summary>
		public DateTime To
		{
			get { return (DateTime)GetValue(ToProperty); }
			set { SetValue(ToProperty, value); }
		}

		/// <summary>
		/// <see cref="DependencyProperty"/> для <see cref="AutoReset"/>.
		/// </summary>
		public static readonly DependencyProperty AutoResetProperty = DependencyProperty.Register("AutoReset", typeof(bool), typeof(EmulationControlPanel), new PropertyMetadata(true));

		/// <summary>
		/// Автоматически сбрасывать состояние при остановке эмуляции.
		/// </summary>
		public bool AutoReset
		{
			get { return (bool)GetValue(AutoResetProperty); }
			set { SetValue(AutoResetProperty, value); }
		}

		/// <summary>
		/// Сбросить состояние панели для управления процессом эмуляции.
		/// </summary>
		public void Reset()
		{
			if(EmulationTrader == null || EmulationTrader.State != EmulationStates.Stopped)
				throw new InvalidOperationException("Невозможно выполнить сброс панели для управления процессом эмуляции.");

			Progress.Value = 0;
			Start.IsEnabled = true;
		}

		private void EmulationTraderOnStateChanged(EmulationStates prev, EmulationStates curr)
		{
			switch (curr)
			{
				case EmulationStates.Stopped:
					GuiDispatcher.GlobalDispatcher.AddAction(() =>
					{
						Start.IsEnabled = false;
						Pause.IsEnabled = false;
						Stop.IsEnabled = false;

						if (AutoReset)
							Reset();
					});
					break;
				case EmulationStates.Stopping:
					GuiDispatcher.GlobalDispatcher.AddAction(() =>
					{
						Start.IsEnabled = false;
						Pause.IsEnabled = false;
						Stop.IsEnabled = false;
					});
					break;
				case EmulationStates.Starting:
				case EmulationStates.Started:
					GuiDispatcher.GlobalDispatcher.AddAction(() =>
					{
						Start.IsEnabled = false;
						Pause.IsEnabled = true;
						Stop.IsEnabled = true;
					});
					break;
				case EmulationStates.Suspending:
					GuiDispatcher.GlobalDispatcher.AddAction(() =>
					{
						Start.IsEnabled = false;
						Pause.IsEnabled = false;
						Stop.IsEnabled = false;
					});
					break;
				case EmulationStates.Suspended:
					GuiDispatcher.GlobalDispatcher.AddAction(() =>
					{
						Start.IsEnabled = true;
						Pause.IsEnabled = false;
						Stop.IsEnabled = true;
					});
					break;
				default:
					throw new ArgumentOutOfRangeException("curr");
			}
		}

		private void Start_Click(object sender, RoutedEventArgs e)
		{
			if (EmulationTrader.State == EmulationStates.Suspended)
				EmulationTrader.Resume();
			else
			{
				_stopTime = To;

				_progressStep = ((To - From).Ticks / 100).To<TimeSpan>();
				_nextTime = From + _progressStep;

				Progress.Maximum = 100;
				Progress.Value = 0;

				EmulationTrader.Start(From, To);
			}
		}

		private void Pause_Click(object sender, RoutedEventArgs e)
		{
			EmulationTrader.Suspend();
		}

		private void Stop_Click(object sender, RoutedEventArgs e)
		{
			EmulationTrader.Stop();
		}
	}
}